package com.rslai.base.tool.servertest.intercept;

import com.alibaba.fastjson.JSON;
import com.rslai.base.tool.servertest.command.StepCommand;
import com.rslai.base.tool.servertest.context.Context;
import com.rslai.base.tool.servertest.model.KeyValueStore;
import com.rslai.base.tool.servertest.response.Response;
import com.rslai.base.tool.servertest.transport.http.HttpService;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;

public class UploadFileInterceptor extends ParameterInterceptor {
    private static final String CONTENT_TYPE = "Content-Type";
    private static final String HTTP_HEADERS = "http-headers";

    protected List<KeyValueStore> convert(List<KeyValueStore> params) {
        List parameters = removedHeaders(params);
        FileUploadWriter fileUploadWriter = new FileUploadWriter();
        fileUploadWriter.write(parameters);

        KeyValueStore httpHeaders = newHttpHeaders(params, fileUploadWriter);

        List result = new ArrayList();
        result.add(httpHeaders);
        result.add(new KeyValueStore("param", fileUploadWriter.toByteArray()));
        IOUtils.closeQuietly(fileUploadWriter);
        return result;
    }

    public Object afterExecute(StepCommand command, Response response, Context context) {
        HttpService.removeHeader("Content-Type");
        return response;
    }

    private KeyValueStore newHttpHeaders(List<KeyValueStore> params, FileUploadWriter fileUploadWriter) {
        KeyValueStore httpHeaders = extractHttpHeaders(params);
        Map headers = tryParseObject(httpHeaders.getValue());
        headers.put("Content-Type", "multipart/form-data; boundary=" + fileUploadWriter.getBoundary());
        return httpHeaders;
    }

    protected boolean support(List<KeyValueStore> params) {
        KeyValueStore httpHeaders = extractHttpHeaders(params);
        return isMultipart(httpHeaders);
    }

    private boolean isMultipart(KeyValueStore httpHeaders) {
        if (httpHeaders == null) return false;
        Map headers = tryParseObject(httpHeaders.getValue());
        Object contentType = headers.get("Content-Type");
        if (contentType == null) return false;
        String contentTypeStr = contentType.toString();
        if (!StringUtils.startsWith(contentTypeStr, "multipart/form-data")) return false;
        return true;
    }

    private List<KeyValueStore> removedHeaders(List<KeyValueStore> commandParameters) {
        List result = new ArrayList();
        for (KeyValueStore commandParameter : commandParameters) {
            if (!commandParameter.getName().equalsIgnoreCase("http-headers")) {
                result.add(commandParameter);
            }
        }
        return result;
    }

    private KeyValueStore extractHttpHeaders(List<KeyValueStore> commandParameters) {
        for (KeyValueStore parameter : commandParameters) {
            if (parameter.getName().equals("http-headers")) return parameter;
        }
        return null;
    }

    /**
     * json字符串转map对象
     * @param value json字符串
     * @return Map
     */
    private static Map tryParseObject(Object value) {
        if (value instanceof String) {
            try {
                Map map = JSON.parseObject(value.toString());
                if (null == map) {
                    map = new HashMap();
                }
                return map;
            } catch (Exception e) {
                throw new RuntimeException(String.format("<%s>尝试转JSONObject失败, error message=%s", new Object[]{value, e.getMessage()}), e);
            }
        } else if (value instanceof Map) {
            return (Map) value;
        } else {
            throw new RuntimeException(String.format("<%s>返回map失败", new Object[]{value}));
        }
    }
}
